package com.example.blog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.blog.dao.mapper.*;
import com.example.blog.dao.pojo.*;
import com.example.blog.dao.pojo.Collection;
import com.example.blog.service.*;
import com.example.blog.utils.UserThreadLocal;
import com.example.blog.vo.ArticleBodyVo;
import com.example.blog.vo.ArticleVo;
import com.example.blog.vo.Result;
import com.example.blog.vo.TagVo;
import com.example.blog.vo.params.ArticleParam;
import com.example.blog.vo.params.PageParams;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleMapper articleMapper;
    @Autowired
    private TagMapper tagMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LoginService loginService;
    @Autowired
    private ArticleBlogTagMapper articleBlogTagMapper;
    @Autowired
    private CollectionMapper collectionMapper;
    @Autowired
    private LikeMapper likeMapper;
    @Autowired
    private ThreadService threadService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private ArticleBodyMapper articleBodyMapper;


    /**
     * 分页查询article 数据库
     */
    @Override
    public Result listArticle(String token, PageParams pageParams) {

        Page<Article> page = new Page<Article>(pageParams.getPage(),pageParams.getPageSize());

        LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();

        if (pageParams.getCategoryId() != null) {
            queryWrapper.eq(Article::getCategoryId, pageParams.getCategoryId());
        }
        List<Long> articleIdList = new ArrayList<>();
        if (pageParams.getTagId() != null) {
            LambdaQueryWrapper<ArticleBlogTag> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(ArticleBlogTag::getTagId, pageParams.getTagId());
            List<ArticleBlogTag> articleBlogTags =articleBlogTagMapper.selectList(lambdaQueryWrapper);
            for (ArticleBlogTag articleBlogTag : articleBlogTags) {
                articleIdList.add(articleBlogTag.getArticleId());
            }
            if (articleIdList.size() > 0) {
                queryWrapper.in(Article::getAid, articleIdList);
            }
        }

        if (pageParams.getStatus() != null && !pageParams.getStatus().equals("")) {
            if (pageParams.getStatus().equals("new")) {
                queryWrapper.orderByDesc(Article::getPublishTime);
            } else if (pageParams.getStatus().equals("hot")) {
                queryWrapper.orderByDesc(Article::getViewCounts);
            }
        } else {
            queryWrapper.orderByDesc(Article::getLikesCounts);
        }

        if (pageParams.getAuthorId() != null) {
            queryWrapper.eq(Article::getAuthorId, pageParams.getAuthorId());
        }

        if (pageParams.getArticleId() != null) {
            queryWrapper.eq(Article::getAid, pageParams.getArticleId());
        }

        List<Long> likeArticleIds = new ArrayList<>();
        List<Long> collectionArticleIds = new ArrayList<>();
        if (!token.equals("Bearer null")) {
            Long userId = this.loginService.checkToken(token).getId();
            LambdaQueryWrapper<Like> likeLambdaQueryWrapper = new LambdaQueryWrapper<>();
            likeLambdaQueryWrapper.eq(Like::getUserId, userId);
            List<Like> likes = this.likeMapper.selectList(likeLambdaQueryWrapper);
            if (likes.size() > 0){
                for (Like like : likes) {
                    likeArticleIds.add(like.getArticleId());
                }
            }

            LambdaQueryWrapper<Collection> cLambdaQueryWrapper = new LambdaQueryWrapper<>();
            cLambdaQueryWrapper.eq(Collection::getUserId, userId);
            List<Collection> collections = this.collectionMapper.selectList(cLambdaQueryWrapper);
            if (collections.size() > 0){
                for (Collection collection : collections) {
                    collectionArticleIds.add(collection.getArticleId());
                }
            }

        }

        Page<Article> articlePage = this.articleMapper.selectPage(page, queryWrapper);
        List<Article> records = articlePage.getRecords();
        List<ArticleVo> articleVoList = copyList(records);

        if (likeArticleIds.size() > 0) {
            for (ArticleVo articleVo : articleVoList) {
                if (likeArticleIds.contains(articleVo.getId())) {
                    articleVo.setIsLike(true);
                }
            }
        }

        if (collectionArticleIds.size() > 0) {
            for (ArticleVo articleVo : articleVoList) {
                if (collectionArticleIds.contains(articleVo.getId())) {
                    articleVo.setIsCollection(true);
                }
            }
        }

        return Result.success(articleVoList);
    }

    /**
     * 1、根据id查询文章信息
     * 2、根据bodyID 和categoryId关联查询
     */
    @Override
    public Result findArticleById(String token, Long articleId){
        Article article = articleMapper.selectById(articleId);
        ArticleVo articleVo = copy(article, true, true, true, true);
        if (!token.equals("Bearer null")) {
            Long userId = loginService.checkToken(token).getId();
            LambdaQueryWrapper<Like> likeLambdaQueryWrapper = new LambdaQueryWrapper<>();
            likeLambdaQueryWrapper.eq(Like::getUserId, userId);
            likeLambdaQueryWrapper.eq(Like::getArticleId, articleId);
            Like like = likeMapper.selectOne(likeLambdaQueryWrapper);
            if (like != null) {
                articleVo.setIsLike(true);
            }

            LambdaQueryWrapper<Collection> collectionLambdaQueryWrapper = new LambdaQueryWrapper<>();
            collectionLambdaQueryWrapper.eq(Collection::getUserId, userId);
            collectionLambdaQueryWrapper.eq(Collection::getArticleId, articleId);
            Collection collection = collectionMapper.selectOne(collectionLambdaQueryWrapper);
            if (collection != null) {
                articleVo.setIsCollection(true);
            }
        }
            // 点击查看文章时 浏览量需要增长 ，这时候做更新操作，更新时加写锁  会阻塞其他的读操作
            //更新 增加了此次接口的耗时 如果更新一旦出问题，不能影响查看文章的操作
            //使用线程池解决该问题 可以把更新操作扔到线程池中去执行，这样就不会影响主线程的操作了
        this.threadService.updateArticleViewCount(this.articleMapper, article);
        return Result.success(articleVo);
    }

    @Override
    public Result likesAdd(String token, Long articleId) {
        /**
         * 1、根据id查询文章信息
         * 2、根据bodyID 和categoryId关联查询
         */
        if (token.equals("Bearer null")) {
            return Result.fail(-999, "授权过期");
        } else {
            Long userId = loginService.checkToken(token).getId();
            LambdaQueryWrapper<Like> likeLQW = new LambdaQueryWrapper<>();
            likeLQW.eq(Like::getUserId, userId);
            likeLQW.eq(Like::getArticleId, articleId);
            Like selectOne = likeMapper.selectOne(likeLQW);

            Article article = articleMapper.selectById(articleId);
            LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Article::getAid,articleId);

            if (selectOne == null) {
                Like like = new Like();
                like.setUserId(userId);
                like.setArticleId(articleId);
                like.setCreateTime(new Date());
                likeMapper.insert(like);
                article.setLikesCounts(article.getLikesCounts()+1);
                articleMapper.update(article,queryWrapper);
                return Result.success(true);
            } else {
                likeMapper.delete(likeLQW);
                article.setLikesCounts(article.getLikesCounts()-1);
                articleMapper.update(article,queryWrapper);
                return Result.success(false);
            }
        }
    }

    @Override
    public Result publish(ArticleParam articleParam) {
        User user = UserThreadLocal.get();

        /**
         * 1、发布文章 构建article对象
         * 2、作者id 当前的登录用户
         * 3、标签 将当前的标签加入关联表中
         * 4、body 内容存储 article
         */
        Article article = new Article();
        article.setAuthorId(user.getId());
        article.setTitle(articleParam.getTitle());
        article.setSummary(articleParam.getSummary());
        Date date = new Date();
        article.setPublishTime(date);
        article.setUpdateTime(date);
        article.setCategoryId(articleParam.getCategory().getCid());
        article.setIsTop(0);
        article.setIsDraft(0);
        article.setIsDelete(0);
        article.setViewCounts(0);
        article.setCommentCounts(0);
        article.setLikesCounts(0);
        article.setCover(articleParam.getCover());
        //插入之后会生成一个文章id
        this.articleMapper.insert(article);
        //tag
        List<TagVo> tags = articleParam.getTags();
        System.out.println(tags);
        if (tags != null){
            for (TagVo tag : tags) {
                Long articleId = article.getAid();
                ArticleBlogTag articleTag = new ArticleBlogTag();
                articleTag.setId(null);
                articleTag.setTagId(tag.getTid());
                articleTag.setArticleId(articleId);
                articleBlogTagMapper.insert(articleTag);
            }
        }
        //body
        ArticleBody body = new ArticleBody();
        body.setArticleId(article.getAid());
        body.setContent(articleParam.getBody().getContent());
        body.setContentHtml(articleParam.getBody().getContentHtml());
        articleBodyMapper.insert(body);
        article.setBodyId(body.getId());
        articleMapper.updateById(article);
        Map<String ,String> map = new HashMap<>();
        map.put("id",article.getAuthorId().toString());
        return Result.success(map);
    }

    @Override
    public Result change(ArticleParam articleParam) {
        User user = UserThreadLocal.get();
        Article article = new Article();
        article.setAuthorId(user.getId());
        article.setTitle(articleParam.getTitle());
        article.setSummary(articleParam.getSummary());
        Date date = new Date();
        article.setUpdateTime(date);
        article.setCategoryId(articleParam.getCategory().getCid());
        article.setCover(articleParam.getCover());
        LambdaQueryWrapper<Article> articleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        articleLambdaQueryWrapper.eq(Article::getAid, article.getAid());
        this.articleMapper.update(article, articleLambdaQueryWrapper);
        LambdaQueryWrapper<ArticleBlogTag> tagLambdaQueryWrapper = new LambdaQueryWrapper<>();
        tagLambdaQueryWrapper.eq(ArticleBlogTag::getArticleId, article.getAid());
        this.articleBlogTagMapper.delete(tagLambdaQueryWrapper);
        List<TagVo> tags = articleParam.getTags();
        Long articleId = article.getAid();
        if (tags != null) {
            for (TagVo tag : tags) {
                ArticleBlogTag articleTag = new ArticleBlogTag();
                articleTag.setTagId(tag.getTid());
                articleTag.setArticleId(articleId);
                this.articleBlogTagMapper.insert(articleTag);
            }
        }
        ArticleBody body = new ArticleBody();
        body.setContent(articleParam.getBody().getContent());
        body.setContentHtml(articleParam.getBody().getContentHtml());
        LambdaQueryWrapper<ArticleBody> bodyLambdaQueryWrapper = new LambdaQueryWrapper<>();
        bodyLambdaQueryWrapper.eq(ArticleBody::getArticleId, article.getAid());
        this.articleBodyMapper.update(body, bodyLambdaQueryWrapper);
        return Result.success("更新成功");
    }
    @Override
    public Result addCollection(String token, Long articleId) {
        if (token.equals("Bearer null")) {
            return Result.fail(-999, "授权过期");
        } else {
            Long userId = loginService.checkToken(token).getId();
            LambdaQueryWrapper<Collection> collectionLQW = new LambdaQueryWrapper<>();
            collectionLQW.eq(Collection::getUserId, userId);
            collectionLQW.eq(Collection::getArticleId, articleId);
            Collection selectOne = collectionMapper.selectOne(collectionLQW);

            Article article = articleMapper.selectById(articleId);
            LambdaQueryWrapper<Article> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Article::getAid,articleId);

            if (selectOne == null) {
                Collection collection = new Collection();
                collection.setUserId(userId);
                collection.setArticleId(articleId);
                collection.setCreateTime(new Date());
                this.collectionMapper.insert(collection);
                article.setLikesCounts(article.getLikesCounts()+1);
                articleMapper.update(article,queryWrapper);
                return Result.success(true);
            } else {
                this.collectionMapper.delete(collectionLQW);
                article.setLikesCounts(article.getLikesCounts()-1);
                articleMapper.update(article,queryWrapper);
                return Result.success(false);
            }
        }
    }


    public List<ArticleVo> copyList(List<Article> records) {
        List<ArticleVo> articleVoList = new ArrayList<>();
        for (Article record : records) {
            articleVoList.add(copy(record,true,true,false,false));
        }

        return articleVoList;
    }
    private List<ArticleVo> copyList(List<Article> records,boolean isTag, boolean isAuthor,boolean isBody,boolean isCategory) {
        List<ArticleVo> articleVoList = new ArrayList<>();
        for (Article record : records) {
            articleVoList.add(copy(record,true,true,isBody,isCategory));
        }

        return articleVoList;
    }


    private ArticleVo copy(Article article, boolean isTag, boolean isAuthor,boolean isBody,boolean isCategory){
        ArticleVo articleVo = new ArticleVo();
        BeanUtils.copyProperties(article,articleVo);
        articleVo.setPublishTime(new DateTime(article.getPublishTime()).toString("yyyy-MM-dd HH:mm:ss"));
        articleVo.setId(article.getAid());



        if (isTag) {
            List<TagVo> tags = tagMapper.findTagsByArticleId(articleVo.getId());
            articleVo.setTags(tags);
        }
        if (isAuthor) {

            articleVo.setAuthorId(article.getAuthorId());
            articleVo.setNickname(userMapper.selectById(article.getAuthorId()).getNickname());
        }
        if (isBody){
            Long bodyId = article.getBodyId();
            articleVo.setBody(findArticleBodyById(bodyId));

        }
        if (isCategory){
            Long categoryId = article.getCategoryId();
            articleVo.setCategory(categoryService.findCategoryById(categoryId));
        }
        return articleVo;

    }


    private ArticleBodyVo findArticleBodyById(Long bodyId) {
        ArticleBody articleBody = articleBodyMapper.selectById(bodyId);
        ArticleBodyVo articleBodyVo = new ArticleBodyVo();
//        articleBodyVo.setContentHtml(articleBody.getContentHtml());
        BeanUtils.copyProperties(articleBody,articleBodyVo);
        return articleBodyVo;
    }
}
